using System.Reflection;

using log4net.Appender;

using Microsoft.Practices.Unity;

using Ncqrs.Bus;
using Ncqrs.Bus.NServiceBus;
using Ncqrs.CommandExecution.AutoMapping;
using Ncqrs.CommandHandling;
using Ncqrs.CommandHandling.Dispatching;
using Ncqrs.Domain;
using Ncqrs.Domain.Bus;
using Ncqrs.EventSourcing.EntityFramework;
using Ncqrs.EventSourcing.Storage;
using Ncqrs.Infrastructure;

using NServiceBus;

using TheKitchen.Commanding.Commands;

namespace TheKitchen.Commanding
{
    public class Bootstrapper
    {
        public void Start()
        {
            SetupDependencies();

            InitializeNServiceBus();
        }

        private static void SetupDependencies()
        {
            var container = ServiceLocator.Current;

            var dispatcher = new InProcessCommandExecutionDispatcher();

            dispatcher.RegisterExecutorForAllCommandsIn(
                Assembly.GetAssembly(typeof (AddNewRecipeCommand)),
                new AutoMappingCommandExecutor());

            container.RegisterType<IUniqueIdentifierGenerator, BasicGuidGenerator>(
                new ContainerControlledLifetimeManager());
            container.RegisterInstance<ICommandExecutor>(dispatcher, new ContainerControlledLifetimeManager());
            container.RegisterInstance<IPropertyBagConverter>(new PropertyBagConverter());
            container.RegisterType<IEventStore, EntityFrameworkEventStore>(new ContainerControlledLifetimeManager());
            container.RegisterType<IEventBus, DistributedEventBus>();
            container.RegisterType<IUnitOfWorkFactory, ThreadBasedUnitOfWorkFactory>();
        }

        private static void InitializeNServiceBus()
        {
            SetLoggingLibrary.Log4Net(log4net.Config.XmlConfigurator.Configure);

            IBus bus = Configure.WithWeb()
                .Log4Net<FileAppender>(a =>
                {
                    a.AppendToFile = false;
                    a.File = ".\\nservicebus.log";
                })  
                .DefaultBuilder()
                .XmlSerializer()
                .MsmqTransport().IsTransactional(true)
                .MsmqSubscriptionStorage()
                .UnicastBus()
                    .LoadMessageHandlers()
                .CreateBus()
                .Start();

            ServiceLocator.Current.RegisterInstance(new DistributedEventBus(bus));
        }
    }
}